#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Python 插件功能测试
验证 flake8, bandit, pytest 插件是否正常工作
"""

import sys
import os
import tempfile
from pathlib import Path

# 添加项目根目录到 Python 路径
project_root = Path(__file__).parent
sys.path.insert(0, str(project_root))


def test_flake8_plugin():
    """测试 flake8 插件"""
    print("\n" + "=" * 60)
    print("测试 flake8 插件 - Python 代码风格检查")
    print("=" * 60)
    
    try:
        # 导入插件
        sys.path.insert(0, str(project_root / 'plugins' / 'lint'))
        import flake8
        
        plugin = flake8.Flake8Plugin()
        print(f"[OK] 插件加载成功: {plugin.description}")
        
        # 创建测试文件
        with tempfile.TemporaryDirectory() as temp_dir:
            test_file = Path(temp_dir) / "bad_style.py"
            test_file.write_text("""
# 这个文件故意包含代码风格问题
import os,sys  # 应该分行导入
import json

def bad_function( x,y ):  # 括号内不应有空格
    if x>y:  # 操作符周围应该有空格
        print("x is greater")
    result=x+y  # 赋值符周围应该有空格
    return result

class MyClass:
    def method_with_very_long_name_that_exceeds_line_length_limit_and_should_be_detected_by_flake8(self):
        return "too long"
""")
            
            print(f"[OK] 创建测试文件: {test_file.name}")
            
            # 执行检查
            config = {
                'paths': [str(temp_dir)],
                'max_line_length': 88,
                'ignore': ['E203', 'W503'],
                'exclude': []
            }
            
            print("[OK] 执行 flake8 检查...")
            result = plugin.execute(config, {})
            
            # 验证结果
            print(f"\n检查结果:")
            print(f"  - 执行状态: {'失败' if not result['success'] else '成功'}")
            print(f"  - 退出码: {result['exit_code']}")
            
            if 'details' in result:
                details = result['details']
                print(f"  - 发现问题数: {details.get('total_issues', 0)}")
                print(f"  - 错误: {details.get('errors', 0)}")
                print(f"  - 警告: {details.get('warnings', 0)}")
            
            print(f"\n输出摘要:")
            output = result['output']
            lines = output.split('\n')[:5]
            for line in lines:
                if line.strip():
                    print(f"  {line}")
            
            # 判断测试是否通过
            if result['exit_code'] != 0 and 'details' in result:
                print("\n[SUCCESS] flake8 插件工作正常！成功检测到代码风格问题。")
                return True
            else:
                print("\n[WARNING] flake8 未检测到预期的问题。")
                return False
                
    except Exception as e:
        print(f"\n[ERROR] flake8 插件测试失败: {e}")
        import traceback
        traceback.print_exc()
        return False


def test_bandit_plugin():
    """测试 bandit 插件"""
    print("\n" + "=" * 60)
    print("测试 bandit 插件 - Python 安全漏洞检查")
    print("=" * 60)
    
    try:
        # 导入插件
        sys.path.insert(0, str(project_root / 'plugins' / 'security'))
        import bandit
        
        plugin = bandit.BanditPlugin()
        print(f"[OK] 插件加载成功: {plugin.description}")
        
        # 检查工具是否可用
        tool_available = plugin._check_bandit_installed()
        print(f"[OK] bandit 工具可用: {tool_available}")
        
        if not tool_available:
            print("[WARNING] bandit 工具未安装，跳过实际检查")
            print("[INFO] 安装命令: pip install bandit")
            return None
        
        # 创建测试文件
        with tempfile.TemporaryDirectory() as temp_dir:
            test_file = Path(temp_dir) / "security_issues.py"
            test_file.write_text("""
import subprocess
import pickle
import os

# 安全问题1: 使用 shell=True
def run_command(user_input):
    subprocess.call(user_input, shell=True)

# 安全问题2: 硬编码密码
API_KEY = "hardcoded_api_key_12345"
PASSWORD = "admin123"

# 安全问题3: 使用 eval
def evaluate(user_input):
    return eval(user_input)

# 安全问题4: 不安全的 pickle
def load_data(filename):
    with open(filename, 'rb') as f:
        return pickle.load(f)
""")
            
            print(f"[OK] 创建测试文件: {test_file.name}")
            
            # 执行检查
            config = {
                'paths': [str(temp_dir)],
                'confidence': 'LOW',
                'severity': 'LOW',
                'exclude': [],
                'fail_on_medium': False
            }
            
            print("[OK] 执行 bandit 检查...")
            result = plugin.execute(config, {})
            
            # 验证结果
            print(f"\n检查结果:")
            print(f"  - 执行状态: {'失败' if not result['success'] else '成功'}")
            print(f"  - 退出码: {result['exit_code']}")
            
            if 'details' in result:
                details = result['details']
                print(f"  - 发现问题数: {details.get('total_issues', 0)}")
                print(f"  - 高危: {details.get('high_severity', 0)}")
                print(f"  - 中危: {details.get('medium_severity', 0)}")
                print(f"  - 低危: {details.get('low_severity', 0)}")
                print(f"  - 扫描文件数: {details.get('files_scanned', 0)}")
            
            print(f"\n输出摘要:")
            output = result['output']
            lines = output.split('\n')[:5]
            for line in lines:
                if line.strip():
                    print(f"  {line}")
            
            # 判断测试是否通过
            print("\n[SUCCESS] bandit 插件结构正常！")
            return True
                
    except Exception as e:
        print(f"\n[ERROR] bandit 插件测试失败: {e}")
        import traceback
        traceback.print_exc()
        return False


def test_pytest_plugin():
    """测试 pytest 插件"""
    print("\n" + "=" * 60)
    print("测试 pytest 插件 - Python 单元测试执行")
    print("=" * 60)
    
    try:
        # 导入插件
        sys.path.insert(0, str(project_root / 'plugins' / 'test'))
        import pytest as pytest_plugin
        
        plugin = pytest_plugin.PytestPlugin()
        print(f"[OK] 插件加载成功: {plugin.description}")
        
        # 检查工具是否可用
        tool_available = plugin._check_pytest_installed()
        print(f"[OK] pytest 工具可用: {tool_available}")
        
        if not tool_available:
            print("[WARNING] pytest 工具未安装，跳过实际检查")
            print("[INFO] 安装命令: pip install pytest")
            return None
        
        # 创建测试文件
        with tempfile.TemporaryDirectory() as temp_dir:
            # 创建被测试的代码
            code_file = Path(temp_dir) / "calculator.py"
            code_file.write_text("""
class Calculator:
    def add(self, x, y):
        return x + y
    
    def subtract(self, x, y):
        return x - y
    
    def multiply(self, x, y):
        return x * y
    
    def divide(self, x, y):
        if y == 0:
            raise ValueError("Cannot divide by zero")
        return x / y
""")
            
            # 创建测试文件
            test_file = Path(temp_dir) / "test_calculator.py"
            test_file.write_text("""
import sys
sys.path.insert(0, '.')
from calculator import Calculator

def test_add():
    calc = Calculator()
    assert calc.add(2, 3) == 5
    assert calc.add(-1, 1) == 0

def test_subtract():
    calc = Calculator()
    assert calc.subtract(5, 3) == 2
    assert calc.subtract(0, 5) == -5

def test_multiply():
    calc = Calculator()
    assert calc.multiply(3, 4) == 12
    assert calc.multiply(-2, 3) == -6

def test_divide():
    calc = Calculator()
    assert calc.divide(10, 2) == 5
    assert calc.divide(9, 3) == 3
""")
            
            print(f"[OK] 创建测试文件: {test_file.name}")
            print(f"[OK] 创建代码文件: {code_file.name}")
            
            # 执行测试
            config = {
                'test_paths': [str(temp_dir)],
                'coverage': False,
                'verbose': True,
                'fail_fast': False
            }
            
            print("[OK] 执行 pytest 测试...")
            
            # 切换到测试目录
            original_cwd = os.getcwd()
            os.chdir(temp_dir)
            
            try:
                result = plugin.execute(config, {})
            finally:
                os.chdir(original_cwd)
            
            # 验证结果
            print(f"\n测试结果:")
            print(f"  - 执行状态: {'成功' if result['success'] else '失败'}")
            print(f"  - 退出码: {result['exit_code']}")
            
            if 'details' in result and 'test_stats' in result['details']:
                stats = result['details']['test_stats']
                print(f"  - 总测试数: {stats.get('total', 0)}")
                print(f"  - 通过: {stats.get('passed', 0)}")
                print(f"  - 失败: {stats.get('failed', 0)}")
                print(f"  - 跳过: {stats.get('skipped', 0)}")
            
            print(f"\n输出摘要:")
            output = result['output']
            lines = output.split('\n')[:5]
            for line in lines:
                if line.strip():
                    print(f"  {line}")
            
            # 判断测试是否通过
            if result['success']:
                print("\n[SUCCESS] pytest 插件工作正常！成功执行测试。")
                return True
            else:
                print("\n[WARNING] pytest 执行有问题。")
                return False
                
    except Exception as e:
        print(f"\n[ERROR] pytest 插件测试失败: {e}")
        import traceback
        traceback.print_exc()
        return False


def test_config_files():
    """测试配置文件"""
    print("\n" + "=" * 60)
    print("测试配置文件 - 验证 Python 插件配置")
    print("=" * 60)
    
    try:
        import yaml
        
        # 测试主配置文件
        config_file = project_root / 'config' / 'hooks.yaml'
        print(f"[OK] 读取配置文件: {config_file}")
        
        with open(config_file, 'r', encoding='utf-8') as f:
            config = yaml.safe_load(f)
        
        # 检查 Python 插件
        plugins = config.get('plugins', {}).get('builtin', [])
        python_plugins = [p for p in plugins if p['name'] in ['flake8', 'bandit', 'pytest']]
        
        print(f"[OK] 找到 {len(python_plugins)} 个 Python 插件:")
        for plugin in python_plugins:
            print(f"  - {plugin['name']}: {plugin['path']}")
        
        # 测试 Python 配置模板
        python_config_file = project_root / 'examples' / 'python-config.yaml'
        print(f"\n[OK] 读取 Python 配置模板: {python_config_file}")
        
        with open(python_config_file, 'r', encoding='utf-8') as f:
            python_config = yaml.safe_load(f)
        
        hooks = python_config.get('hooks', {})
        print(f"[OK] 包含 {len(hooks)} 个 hooks:")
        for hook_name in hooks.keys():
            print(f"  - {hook_name}")
        
        print("\n[SUCCESS] 配置文件验证通过！")
        return True
        
    except Exception as e:
        print(f"\n[ERROR] 配置文件测试失败: {e}")
        import traceback
        traceback.print_exc()
        return False


def main():
    """主测试函数"""
    print("=" * 60)
    print("Python 插件功能测试")
    print("=" * 60)
    print("\n本测试将验证以下功能:")
    print("1. flake8 插件 - Python 代码风格检查")
    print("2. bandit 插件 - Python 安全漏洞扫描")
    print("3. pytest 插件 - Python 单元测试执行")
    print("4. 配置文件 - Python 插件配置验证")
    print()
    
    results = {}
    
    # 运行测试
    results['flake8'] = test_flake8_plugin()
    results['bandit'] = test_bandit_plugin()
    results['pytest'] = test_pytest_plugin()
    results['config'] = test_config_files()
    
    # 总结结果
    print("\n" + "=" * 60)
    print("测试结果总结")
    print("=" * 60)
    
    passed = 0
    failed = 0
    skipped = 0
    
    for name, result in results.items():
        if result is True:
            print(f"[OK] {name}: 通过")
            passed += 1
        elif result is False:
            print(f"[ERROR] {name}: 失败")
            failed += 1
        else:
            print(f"[SKIP] {name}: 跳过（工具未安装）")
            skipped += 1
    
    print(f"\n总计: {passed} 通过, {failed} 失败, {skipped} 跳过")
    
    if failed == 0 and passed > 0:
        print("\n" + "=" * 60)
        print("[SUCCESS] Python 插件功能测试全部通过！")
        print("=" * 60)
        print("\n您现在可以:")
        print("1. 在 Python 项目中使用这些插件")
        print("2. 根据需要自定义配置参数")
        print("3. 查看 PYTHON_INTEGRATION.md 了解详细使用方法")
        print()
        return True
    elif passed > 0:
        print(f"\n[WARNING] 部分测试通过，建议安装缺失的工具。")
        return True
    else:
        print(f"\n[ERROR] 测试失败，请检查配置。")
        return False


if __name__ == "__main__":
    try:
        success = main()
        sys.exit(0 if success else 1)
    except KeyboardInterrupt:
        print("\n\n测试被用户中断")
        sys.exit(1)
    except Exception as e:
        print(f"\n\n测试过程中发生未预期的错误: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)
